use ratatui::crossterm::{
    execute,
    terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
use ratatui::prelude::*;
use std::io;
mod rpc;
mod components;
mod event;
mod util;
mod ui;

#[tokio::main]
async fn main() -> io::Result<()> {
    // 初始化终端
    // 原始模式：告诉终端，放弃对所有键盘+鼠标输入的控制权，全部交给程序自身处理。
    // 这就有个问题：常用的ctrl+c无法退出程序，鼠标无法选中内容等
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    // 初始化 App
    let mut app = crate::components::component::App::default();

    // 启用鼠标支持（关键！）这里启用以后，当tui运行的时候，鼠标移动到了tui范围以内就会被隐藏
    // 一旦鼠标被捕获，它的角色就变了。它不再是终端的工具，而是变成了 **rpckit** 这个应用的输入设备。所有的鼠标点击、移动和滚动事件，
    // 都会作为数据发送给你的应用程序（也就是你在 event.rs 中处理的 Event::Mouse），而不是由终端自己处理。
    // 为了跳出这种捕获的监狱，使用shift来移动鼠标
    execute!(io::stdout(), ratatui::crossterm::event::EnableMouseCapture)?;

    const DURATION_TIME_MILLIS: u64 = 33;
    // 主事件循环,由2部分组成，ui + 状态机。各种输入事件和状态机是绑定的，包括网络事件本身也会影响到状态机。
    // 状态机的变化影响ui的渲染，ui的渲染又会触发状态机的变化，从而形成一个闭环
    loop {
        terminal.draw(|f| ui::ui(f, &mut app))?;
        // 如果这里返回了true就会推出tui. 因此用它来控制状态机
        if crate::event::handle_event(&mut app, DURATION_TIME_MILLIS)? {
            break;
        }
        // 检查来自网络任务的事件
        app.process_network_events();
    }

    // 清理终端
    disable_raw_mode()?;

    // 禁用鼠标
    execute!(
        terminal.backend_mut(),
        LeaveAlternateScreen,
        ratatui::crossterm::event::DisableMouseCapture
    )?;

    Ok(())
}
